///implementation of Groovey Particle Set Class

#include "gparticle_set.hpp"
#include <GL/glut.h>

GParticle_Set::GParticle_Set(): spread_X(boost::uniform_int<> (0, 1000)),
								spread_Y(boost::uniform_int<> (0, 1000)),
								dice_X(boost::variate_generator<boost::mt19937&, boost::uniform_int<> > (rng, spread_X)),
								dice_Y(boost::variate_generator<boost::mt19937&, boost::uniform_int<> > (rng, spread_Y))
{
}///////////////////////////Particle Set Constructor

GParticle_Set::GParticle_Set(const int Amount, const GParticle &GPart): 
								spread_X(boost::uniform_int<> (0, 1000)),
								spread_Y(boost::uniform_int<> (0, 1000)),
								dice_X(boost::variate_generator<boost::mt19937&, boost::uniform_int<> > (rng, spread_X)),
								dice_Y(boost::variate_generator<boost::mt19937&, boost::uniform_int<> > (rng, spread_Y))
{
    this->addParticles(Amount,GPart);
}///////////////////////////Particle Set Constructor with initial values

void GParticle_Set::addParticles(const int Amount, 
								const GParticle& GPart)
{
    ////begin with setting the new base particle.
    base = GPart;
    
    ////next we clear our current list
    
    p_set.clear();
    
    ////create a temporary vector for random locations ///NOTE: In the future we give the programmer an option to select the location generator
    boost::numeric::ublas::vector<float> random_vect (2);
    ////now begin populating a new list of particles
    
    for (int i = Amount; i > 0; i--){
        random_vect[0] = dice_X();
        random_vect[1] = dice_Y();
        p_set.push_back(GParticle::GParticle(base.getLife(),base.getSize(),random_vect,base.getVel(),base.getAcc()));
    }
    
    ////the list has been filled. Groovey... Dude...
    
}///////////////////////////add particles()

void GParticle_Set::manipParticles(const GTransformer& Transform)
{
    /////a little manipulation is good for the soul, dude.
    for (std::list<GParticle>::iterator i = p_set.begin(); i != p_set.end(); i++){
        Transform(*i);
    }
}///////////////////////////manipulateParticles()

void GParticle_Set::drawParticles()
{
    ////we need a temporary vector for storing particle locations
    GLfloat X,Y;
    for (std::list<GParticle>::iterator i = p_set.begin(); i != p_set.end(); i++){
        X = i->Loc()[0]/500 - 1;
        Y = i->Loc()[1]/500 - 1;
        glVertex2f(X,Y);
    }
}///////////////////////////drawParticles()

void GParticle_Set::UpdateSet(const int limit_X,
								const int limit_Y)
{
    /////create a random vector in case we need to respawn a particle or two
    boost::numeric::ublas::vector<float> random_vect (2);
    
    ////begin updating particles
    for (std::list<GParticle>::iterator i = p_set.begin(); i != p_set.end(); i++){
        if (i->Dead()){
            ////one died? Oh noes! Quick quick! Particle CPR!
            random_vect[0] = 0.5;// dice_X();
            random_vect[1] = 0.5;// dice_Y();
            i->setLives(base.getLife());
            i->setLoc(random_vect);
            i->setVel(base.getVel());
            i->setAcc(base.getAcc());
            ////our particle is now reset and placed someone within the world. Woo!
        }
        else{
            ////It's.... ALLLIIIVVVVEEE! Update it and check for collisions
        	if (i->Update(limit_X,limit_Y)){
        	    ///uh oh! We hit a wall with this one! Do something! Anything! AHHHHH!!!!!! *booom*
        	    i->Die(1); //bwahahah! Asteroth would love to program this. "Squirm!"
        	}
        }
    }
    
}///////////////////////////UpdateSet()

bool GParticle_Set::howWeRollin()
{
    return !(p_set.empty());
}
